package com.wenlin.myproduction.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

/**
 * @author cwl
 * @desc 波纹荡漾动画自定义控件
 * 原理就是画五个半径从0开始、成等差数列的同心圆，有动画的时候每次慢慢增大半径到公差，并同时减小不透明度，
 * 然后恢复半径再循环这个过程。
 * 而不是五个同心圆半径一直变大到边缘再从0开始。
 * @Email 377979485@qq.com
 * @time 2023/7/14 14:27
 */
public class WaveView extends View {
    private static final int CIRCLE_NUM = 5;//几个同心圆
    private float distanceDelta;//圆与圆之间的距离
    private final int alphaDelta = 10;//各个圆的不透明度的差值
    @ColorInt
    private final int colorFt = Color.parseColor("#FFFFFFFF");//圆的颜色
    private float valueFloat;//动画实时的值
    private Paint paint;
    private ValueAnimator animator;
    private float centerX, centerY;
    private List<Ripple> list;

    public WaveView(Context context) {
        this(context, null);
    }

    public WaveView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setAntiAlias(true);
        paint.setColor(colorFt);
        paint.setDither(true);
        list = new ArrayList<>();
        startAnim();
    }

    /**
     * 开始动画
     */
    private void startAnim() {
        stopAnim();
        animator = ValueAnimator.ofFloat(0, 1);
        animator.addUpdateListener(valueAnimator -> {
            valueFloat = (float) valueAnimator.getAnimatedValue();
            invalidate();
        });
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.setRepeatMode(ValueAnimator.RESTART);
        animator.setDuration(1500);
        animator.setInterpolator(new LinearInterpolator());
        animator.start();
    }

    /**
     * 停止动画
     */
    private void stopAnim() {
        if (animator != null) {
            animator.cancel();
            animator = null;
        }
    }

    /**
     * 初始化集合数据
     */
    private void initListData() {
        for (int i = 0; i < CIRCLE_NUM; i++) {
            list.add(new Ripple(distanceDelta * i + distanceDelta / 2f, (CIRCLE_NUM - 1 - i) * alphaDelta));
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (centerX == 0 || centerY == 0) {
            centerX = getWidth() / 2f;
            centerY = getHeight() / 2f;
            distanceDelta = centerX / CIRCLE_NUM;
            paint.setStrokeWidth(distanceDelta);
        }
        if (list.size() == 0) {
            initListData();
        }
        for (int i = 0; i < list.size(); i++) {
            Ripple ripple = list.get(i);
            paint.setAlpha(Math.max(0, (int) (ripple.getAlpha() - alphaDelta * valueFloat)));
            canvas.drawCircle(centerX, centerY, ripple.getRadius() + distanceDelta * valueFloat, paint);
        }
        paint.setAlpha(255);
        canvas.drawCircle(centerX, centerY, distanceDelta / 2f, paint);//画个白色圆圈，避免中间空心不好看
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        stopAnim();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        startAnim();
    }

    static class Ripple {
        private float radius;
        private int alpha;

        public Ripple(float radius, int alpha) {
            this.radius = radius;
            this.alpha = alpha;
        }

        public float getRadius() {
            return radius;
        }

        public void setRadius(float radius) {
            this.radius = radius;
        }

        public int getAlpha() {
            return alpha;
        }

        public void setAlpha(int alpha) {
            this.alpha = alpha;
        }
    }
}
